<!DOCTYPE html>
<html lang="en">
<head>
		<title>SKiDL &mdash; Reusability Ain't What It Used To Be</title>
		<meta charset="utf-8" />
		<link rel="profile" href="http://gmpg.org/xfn/11" />
		<link rel="stylesheet" type="text/css" href="/skidl/theme/css/style.css" />
		<link rel='stylesheet' id='oswald-css'  href='http://fonts.googleapis.com/css?family=Oswald&#038;ver=3.3.2' type='text/css' media='all' />
		<link rel="preconnect" href="https://fonts.googleapis.com">
		<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
		<link href="https://fonts.googleapis.com/css2?family=Oswald&family=Roboto+Condensed&display=swap" rel="stylesheet">
		<!-- <style type="text/css">
			body.custom-background { background-color: #f5f5f5; }
		</style> -->
		<link rel="alternate" type="application/atom+xml"
			title="SKiDL — Flux Atom"
			href="/skidl/" />
		<!--[if lte IE 8]><script src="/skidl/theme/js/html5shiv.js"></script><![endif]-->
</head>

<body class="home blog custom-background " >
	<div id="container">
		<div id="header">
				<h1 id="site-title"><a href="/skidl"><img src="/skidl/images/banner.png" width="100%"></a></h1>
				<!-- <h1 id="site-title"><a href="/skidl">SKiDL</a></h1> -->
		</div><!-- /#banner -->

		<div id="menu">
			<div class="menu-navigation-container">
				<ul id="menu-navigation" class="menu">
						<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="https://github.com/devbisme/skidl">Github</a></li>
						<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="https://github.com/devbisme/skidl/discussions">Forum</a></li>
						<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="/skidl/category/posts.html">Blog</a></li>
						<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="/skidl/api/html/index.html">API</a></li>
						<li class="menu-item menu-item-type-post_type menu-item-object-page"><a href="/skidl/">Home</a></li>

				</ul>
			</div> <!--/#menu-navigation-container-->
		</div><!-- /#menu -->

		<div class="page-title">
		</div>

		<div id="contents">

<div class="post type-post status-publish format-standard hentry category-general" id="post">
	<div class="entry-meta">
		<span class="date"><a href="/skidl/reuse-leds-2018-05-15.html">Tue 15 May 2018</a></span>
		/
		<span class="byline"><a href="/skidl/author/dave-vandenbout.html">Dave Vandenbout</a></span>
	</div> <!-- /#entry-meta -->
	<div class="main">
		<h2 class="entry-title">
			<a href="/skidl/reuse-leds-2018-05-15.html" title="Permalink to Reusability Ain't What It Used To Be" rel="bookmark">Reusability Ain't What It Used To Be</a>
		</h2>
		<div class="entry-content">
			<p>Sometimes you need a quick circuit that does one, specific thing.
Other times, you want to create a general design that can be re-used in multiple instances.
I'll demonstrate the evolution from a specific to a general SKiDL design using a simple set of LEDs.</p>
<h3 id="four-leds">Four LEDs</h3>
<p>Here's a simple SKiDL module that instantiates four common-cathode LEDs with
current limiting resistors:</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">leds</span><span class="p">(</span><span class="n">inp0</span><span class="p">,</span> <span class="n">inp1</span><span class="p">,</span> <span class="n">inp2</span><span class="p">,</span> <span class="n">inp3</span><span class="p">,</span> <span class="n">gnd</span><span class="p">):</span>

    <span class="c1"># Create four LEDs and resistors.</span>
    <span class="n">leds</span> <span class="o">=</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;LED&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;KiCad/LEDs.pretty:LED_0603&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>
    <span class="n">rs</span> <span class="o">=</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;R&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">&#39;330&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;KiCad/Resistors_SMD.pretty:R_0603&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>

    <span class="c1"># Connect anodes (+) of LEDs to inputs.</span>
    <span class="n">leds</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">&#39;A&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">inp0</span>
    <span class="n">leds</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="s1">&#39;A&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">inp1</span>
    <span class="n">leds</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="s1">&#39;A&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">inp2</span>
    <span class="n">leds</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="s1">&#39;A&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">inp3</span>

    <span class="c1"># Connect current-limiting resistors between LED cathodes (-) and ground.</span>
    <span class="n">rs</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">leds</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">&#39;K&#39;</span><span class="p">],</span> <span class="n">gnd</span>
    <span class="n">rs</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">leds</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="s1">&#39;K&#39;</span><span class="p">],</span> <span class="n">gnd</span>
    <span class="n">rs</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">leds</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="s1">&#39;K&#39;</span><span class="p">],</span> <span class="n">gnd</span>
    <span class="n">rs</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">leds</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="s1">&#39;K&#39;</span><span class="p">],</span> <span class="n">gnd</span>
</code></pre></div>

<p>This module is simple, to-the-point, and limited to four LEDs.
But sometimes you'll want more than that, other times, less.
The next module adds that flexibility.</p>
<h3 id="pick-a-size-leds">Pick-A-Size LEDs</h3>
<p>The module below supports any number of common-cathode LEDs by querying the
number of lines in the input bus and instantiating the required number of components:</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">leds</span><span class="p">(</span><span class="n">inps</span><span class="p">,</span> <span class="n">gnd</span><span class="p">):</span>

    <span class="c1"># Use the width of the input bus to set the number of LEDs and resistors.</span>
    <span class="n">leds</span> <span class="o">=</span> <span class="n">inps</span><span class="o">.</span><span class="n">width</span> <span class="o">*</span> <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;LED&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;KiCad/LEDs.pretty:LED_0603&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>
    <span class="n">rs</span> <span class="o">=</span> <span class="n">inps</span><span class="o">.</span><span class="n">width</span> <span class="o">*</span> <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;R&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">&#39;330&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;KiCad/Resistors_SMD.pretty:R_0603&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>

    <span class="c1"># Zip the inputs, LEDs, and resistors together so there is one input</span>
    <span class="c1"># associated with each LED and resistor. Then, connect them together.</span>
    <span class="k">for</span> <span class="n">inp</span><span class="p">,</span> <span class="n">led</span><span class="p">,</span> <span class="n">r</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">inps</span><span class="p">,</span> <span class="n">leds</span><span class="p">,</span> <span class="n">rs</span><span class="p">):</span>
        <span class="n">led</span><span class="p">[</span><span class="s1">&#39;A&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">inp</span>          <span class="c1"># Connect an LED anode to an input.</span>
        <span class="n">r</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span> <span class="o">+=</span> <span class="n">led</span><span class="p">[</span><span class="s1">&#39;K&#39;</span><span class="p">],</span> <span class="n">gnd</span>  <span class="c1"># Connect a resistor between the LED cathode and ground.</span>
</code></pre></div>

<p>This is more flexible, but a bit less clear and still limited to building
common-cathode LEDs (where the LEDs are turned on by raising their inputs
to a positive voltage).
But I'm out of luck if I want common anode LEDs that light up when I lower
their inputs to ground.
The next module adds that capability.</p>
<h3 id="common-cathode-or-anode">Common-Cathode or Anode?</h3>
<p>The code below supports both common-cathode and common-anode LED configurations
by allowing either the anode or the cathode inputs to be a bus controlling the
individual LEDs while the other input is the common terminal: </p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">leds</span><span class="p">(</span><span class="n">anodes</span><span class="p">,</span> <span class="n">cathodes</span><span class="p">):</span>

    <span class="c1"># Either the anode will be connected to VCC or the cathode will be connected</span>
    <span class="c1"># to ground and will have a width of 1. The width of the other input bus will</span>
    <span class="c1"># determine the number of LEDs.</span>
    <span class="n">width</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">anodes</span><span class="o">.</span><span class="n">width</span><span class="p">,</span> <span class="n">cathodes</span><span class="o">.</span><span class="n">width</span><span class="p">)</span>

    <span class="n">leds</span> <span class="o">=</span> <span class="n">width</span> <span class="o">*</span> <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;LED&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;KiCad/LEDs.pretty:LED_0603&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>
    <span class="n">rs</span> <span class="o">=</span> <span class="n">width</span> <span class="o">*</span> <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;R&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">&#39;330&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;KiCad/Resistors_SMD.pretty:R_0603&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>

    <span class="c1"># Zip the LEDs and resistors together so there is one LED associated with</span>
    <span class="c1"># each resistor. Then, connect them together.</span>
    <span class="k">for</span> <span class="n">led</span><span class="p">,</span> <span class="n">r</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">leds</span><span class="p">,</span> <span class="n">rs</span><span class="p">):</span>
        <span class="n">led</span><span class="p">[</span><span class="s1">&#39;K&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">r</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>

    <span class="c1"># Now connect the anodes inputs to the LED anodes. If anodes is a single wire,</span>
    <span class="c1"># then all the LED anodes will connect to it (common anode). But if the anodes</span>
    <span class="c1"># input is a multi-wire bus, each LED anode will connect to its own bus line.</span>
    <span class="n">anodes</span> <span class="o">+=</span> <span class="p">[</span><span class="n">led</span><span class="p">[</span><span class="s1">&#39;A&#39;</span><span class="p">]</span> <span class="k">for</span> <span class="n">led</span> <span class="ow">in</span> <span class="n">leds</span><span class="p">]</span>

    <span class="c1"># Finally, connect the cathodes input to the other end of the resistors.</span>
    <span class="c1"># If cathodes is a single wire, then all the LED cathodes will connect to</span>
    <span class="c1"># it through their current limiting resistors (common cathode). But if</span>
    <span class="c1"># the cathodes input is a multi-wire bus, each LED cathode will connect</span>
    <span class="c1"># to its own bus line.</span>
    <span class="n">cathodes</span> <span class="o">+=</span> <span class="p">[</span><span class="n">r</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">rs</span><span class="p">]</span>
</code></pre></div>

<p>As a test of the module, I attached three, common-cathode LEDs to a PIC18F
microcontroller unit like this:</p>
<div class="highlight"><pre><span></span><code><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="n">v3_3</span> <span class="o">=</span> <span class="n">Net</span><span class="p">(</span><span class="s1">&#39;+3.3V&#39;</span><span class="p">)</span>
    <span class="n">gnd</span> <span class="o">=</span> <span class="n">Net</span><span class="p">(</span><span class="s1">&#39;GND&#39;</span><span class="p">)</span>
    <span class="n">mcu</span> <span class="o">=</span> <span class="n">Part</span><span class="p">(</span><span class="s1">&#39;MCU_Microchip_pic18&#39;</span><span class="p">,</span> <span class="s1">&#39;pic18f2450-IML&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;xesscorp/xess.pretty:QFN-28&#39;</span><span class="p">)</span>
    <span class="n">mcu</span><span class="p">[</span><span class="s1">&#39;VDD&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">v3_3</span>
    <span class="n">mcu</span><span class="p">[</span><span class="s1">&#39;VSS&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">gnd</span>
    <span class="n">leds</span><span class="p">(</span><span class="n">mcu</span><span class="p">[</span><span class="s1">&#39;RA2, RA3, RA4&#39;</span><span class="p">],</span> <span class="n">gnd</span><span class="p">)</span>  <span class="c1"># Attach 3 common-cathode LEDs.</span>
    <span class="n">ERC</span><span class="p">()</span>
    <span class="n">generate_netlist</span><span class="p">()</span>
</code></pre></div>

<p>And here's a layout for the netlist that was generated:</p>
<p><img alt="Common-cathode LEDs attached to PIC18F MCU." src="images/reuse-leds/leds2.png"></p>
<p>So far, so good. The module is even more general-purpose but it's a bit cost-inefficient
to use all those discrete resistors for limiting the LED current.
The next version of the module will remedy that.</p>
<h3 id="using-resistor-arrays">Using Resistor Arrays</h3>
<p>Replacing discrete resistors with
<a href="https://www.ctscorp.com/wp-content/uploads/74x.pdf">Resistor arrays</a>
containing two, four, or eight independent resistors will lower
the number of components and reduce assembly costs.</p>
<p><img alt="An eight-resistor array." src="images/reuse-leds/742c163.png"></p>
<p><img alt="Resistor pinouts." src="images/reuse-leds/resistor-pinouts.png"></p>
<p>The following code iteratively packs the resistors into one or more arrays
until all the inputs are connected:</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">leds</span><span class="p">(</span><span class="n">anodes</span><span class="p">,</span> <span class="n">cathodes</span><span class="p">):</span>

    <span class="n">width</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">anodes</span><span class="o">.</span><span class="n">width</span><span class="p">,</span> <span class="n">cathodes</span><span class="o">.</span><span class="n">width</span><span class="p">)</span>

    <span class="n">leds</span> <span class="o">=</span> <span class="n">width</span> <span class="o">*</span> <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;LED&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;KiCad/LEDs.pretty:LED_0603&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>

    <span class="c1"># Get various types of resistors.</span>
    <span class="n">R</span>   <span class="o">=</span> <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;R&#39;</span><span class="p">,</span>        <span class="n">value</span><span class="o">=</span><span class="s1">&#39;330&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;KiCad/Resistors_SMD.pretty:R_0603&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>
    <span class="n">RN2</span> <span class="o">=</span> <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;R_Pack02&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">&#39;330&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;xesscorp/xess.pretty:CTS_742C043&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>
    <span class="n">RN4</span> <span class="o">=</span> <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;R_Pack04&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">&#39;330&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;xesscorp/xess.pretty:CTS_742C083&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>
    <span class="n">RN8</span> <span class="o">=</span> <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;R_Pack08&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">&#39;330&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;xesscorp/xess.pretty:CTS_742C163&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">)</span>

    <span class="c1"># Store the resistor types such that their position in the list corresponds</span>
    <span class="c1"># to their use for a specific number of resistors. For example, RN4 is at</span>
    <span class="c1"># list index 5 so it would be selected if five resistors were needed.</span>
    <span class="c1"># (Of course, a four-resistor array would still leave one resistor to be</span>
    <span class="c1"># assigned to some other array.)</span>
    <span class="c1">#            0   1   2    3    4    5    6    7    8</span>
    <span class="n">r_types</span> <span class="o">=</span> <span class="p">[</span><span class="kc">None</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">RN2</span><span class="p">,</span> <span class="n">RN4</span><span class="p">,</span> <span class="n">RN4</span><span class="p">,</span> <span class="n">RN4</span><span class="p">,</span> <span class="n">RN8</span><span class="p">,</span> <span class="n">RN8</span><span class="p">,</span> <span class="n">RN8</span><span class="p">]</span>

    <span class="c1"># The bus width indicates the number of LEDs (and, hence, the number of</span>
    <span class="c1"># resistors) that are needed. Pick the best resistor array and subtract its</span>
    <span class="c1"># size from the number of resistors that are needed. If more resistors are</span>
    <span class="c1"># still required, repeat the loop until the number drops to zero.</span>
    <span class="n">r_needed</span> <span class="o">=</span> <span class="n">width</span>  <span class="c1"># The number of resistors that are currently needed.</span>
    <span class="n">rs</span> <span class="o">=</span> <span class="p">[]</span>           <span class="c1"># Store the selected resistors here.</span>
    <span class="n">left_pins</span> <span class="o">=</span> <span class="p">[]</span>    <span class="c1"># List of pins on the left side of the selected resistors.</span>
    <span class="n">right_pins</span> <span class="o">=</span> <span class="p">[]</span>   <span class="c1"># List of pins on the right side of the selected resistors.</span>

    <span class="k">while</span> <span class="n">r_needed</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>  <span class="c1"># Loop as long as resistors are needed.</span>

        <span class="c1"># Pick the best resistor for the current number of resistors that are needed.</span>
        <span class="c1"># If the needed number is larger than the list of resistors, then pick</span>
        <span class="c1"># the largest available resistor array (which will be at the end of the list).</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">r_type</span> <span class="o">=</span> <span class="n">r_types</span><span class="p">[</span><span class="n">r_needed</span><span class="p">]</span>
        <span class="k">except</span> <span class="ne">IndexError</span><span class="p">:</span>
            <span class="n">r_type</span> <span class="o">=</span> <span class="n">r_types</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>  <span class="c1"># Pick the largest resistor array.</span>

        <span class="n">r</span> <span class="o">=</span> <span class="n">r_type</span><span class="p">()</span>  <span class="c1"># Instantiate the selected resistor.</span>
        <span class="n">rs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">r</span><span class="p">)</span>  <span class="c1"># Add the resistor to the list of selected resistors.</span>

        <span class="n">num_pins</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">pins</span><span class="p">)</span>  <span class="c1"># Number of pins on the selected resistor&#39;s package.</span>
        <span class="n">num_resistors</span> <span class="o">=</span> <span class="n">num_pins</span> <span class="o">//</span> <span class="mi">2</span>  <span class="c1"># Each resistor takes up two pins on the package.</span>

        <span class="c1"># Store the pins on the left and right sides of the resistor.</span>
        <span class="c1"># The pins increase from 1 ... num_pins/2 on the left side, and decrease from</span>
        <span class="c1"># num_pins ... num_pins/2+1 on the right side. This keeps the left and</span>
        <span class="c1"># right pins of each resistor in the package aligned between the lists.</span>
        <span class="n">left_pins</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span> <span class="n">r</span><span class="p">[</span>       <span class="mi">1</span><span class="p">:</span><span class="n">num_pins</span><span class="o">//</span><span class="mi">2</span>  <span class="p">])</span>
        <span class="n">right_pins</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">r</span><span class="p">[</span><span class="n">num_pins</span><span class="p">:</span><span class="n">num_pins</span><span class="o">//</span><span class="mi">2</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span>

        <span class="c1"># Subtract the resistors in the selected package from the number that</span>
        <span class="c1"># are needed and loop until that number goes to zero.</span>
        <span class="n">r_needed</span> <span class="o">-=</span> <span class="n">num_resistors</span>

    <span class="c1"># The number of resistors needed may not fit exactly into the number of </span>
    <span class="c1"># resistors selected (e.g., an eight-resistor array might be used when seven</span>
    <span class="c1"># resistors are needed). Therefore, trim the pin lists to the number of</span>
    <span class="c1"># resistors that are needed. (This may leave some pins on the last-selected</span>
    <span class="c1"># array unconnected.) Also, put them on buses so they&#39;ll be easy to connect to.</span>
    <span class="n">left_pins</span>  <span class="o">=</span> <span class="n">Bus</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="n">left_pins</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="n">width</span><span class="p">])</span>
    <span class="n">right_pins</span> <span class="o">=</span> <span class="n">Bus</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="n">right_pins</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="n">width</span><span class="p">])</span>

    <span class="n">anodes</span> <span class="o">+=</span> <span class="p">[</span><span class="n">led</span><span class="p">[</span><span class="s1">&#39;A&#39;</span><span class="p">]</span> <span class="k">for</span> <span class="n">led</span> <span class="ow">in</span> <span class="n">leds</span><span class="p">]</span>     <span class="c1"># Connect LED anodes to anode inputs.</span>
    <span class="n">left_pins</span> <span class="o">+=</span> <span class="p">[</span><span class="n">led</span><span class="p">[</span><span class="s1">&#39;K&#39;</span><span class="p">]</span> <span class="k">for</span> <span class="n">led</span> <span class="ow">in</span> <span class="n">leds</span><span class="p">]</span>  <span class="c1"># Connect LED cathodes to left side of resistors.</span>
    <span class="n">cathodes</span> <span class="o">+=</span> <span class="n">right_pins</span>                   <span class="c1"># Connect right side of resistors to cathode inputs.</span>
</code></pre></div>

<p>Now I'll test the module by attaching five, common-anode LEDs to a microcontroller as follows:</p>
<div class="highlight"><pre><span></span><code>    <span class="n">v3_3</span> <span class="o">=</span> <span class="n">Net</span><span class="p">(</span><span class="s1">&#39;+3.3V&#39;</span><span class="p">)</span>
    <span class="n">gnd</span> <span class="o">=</span> <span class="n">Net</span><span class="p">(</span><span class="s1">&#39;GND&#39;</span><span class="p">)</span>
    <span class="n">mcu</span> <span class="o">=</span> <span class="n">Part</span><span class="p">(</span><span class="s1">&#39;MCU_Microchip_pic18&#39;</span><span class="p">,</span> <span class="s1">&#39;pic18f2450-IML&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;xesscorp/xess.pretty:QFN-28&#39;</span><span class="p">)</span>
    <span class="n">mcu</span><span class="p">[</span><span class="s1">&#39;VDD&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">v3_3</span>
    <span class="n">mcu</span><span class="p">[</span><span class="s1">&#39;VSS&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="n">gnd</span>
    <span class="n">leds</span><span class="p">(</span><span class="n">v3_3</span><span class="p">,</span> <span class="n">mcu</span><span class="p">[</span><span class="s1">&#39;RA[2:6]&#39;</span><span class="p">])</span>  <span class="c1"># Attach 5 common-anode LEDs.</span>
    <span class="n">ERC</span><span class="p">()</span>
    <span class="n">generate_netlist</span><span class="p">()</span>
</code></pre></div>

<p>From the layout, you can see the five current-limiting resistors have been packed into a four-resistor
array and an additional discrete resistor:</p>
<p><img alt="Common-anodes LEDs attached to PIC18F MCU." src="images/reuse-leds/leds4.png"></p>
<p>Up to this point, all the components used in these modules have been hard-coded.
While I might consider myself a great designer with impeccable taste in choosing parts,
you'll probably still want to select components that match your application.
(You mean an 0603 LED isn't perfect for <em>everything?</em>)
This is the last limitation I'll address in this post.</p>
<h3 id="but-i-want-to-use-my-resistors-and-leds">"But I Want To Use <strong>My</strong> Resistors and LEDs!"</h3>
<p>The module shown below uses Python's default argument feature so you can pass
your own choices for components, but it will use the hard-coded components by
default if you don't:</p>
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">leds</span><span class="p">(</span><span class="n">anodes</span><span class="p">,</span> <span class="n">cathodes</span><span class="p">,</span>
        <span class="n">led_type</span> <span class="o">=</span> <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;LED&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;KiCad/LEDs.pretty:LED_0603&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">),</span>
        <span class="n">r_types</span> <span class="o">=</span> <span class="p">[</span>
            <span class="kc">None</span><span class="p">,</span>
            <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;R&#39;</span><span class="p">,</span>        <span class="n">value</span><span class="o">=</span><span class="s1">&#39;330&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;KiCad/Resistors_SMD.pretty:R_0603&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">),</span>
            <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;R_Pack02&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">&#39;330&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;xesscorp/xess.pretty:CTS_742C043&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">),</span>
            <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;R_Pack04&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">&#39;330&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;xesscorp/xess.pretty:CTS_742C083&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">),</span>
            <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;R_Pack04&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">&#39;330&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;xesscorp/xess.pretty:CTS_742C083&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">),</span>
            <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;R_Pack04&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">&#39;330&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;xesscorp/xess.pretty:CTS_742C083&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">),</span>
            <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;R_Pack08&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">&#39;330&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;xesscorp/xess.pretty:CTS_742C163&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">),</span>
            <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;R_Pack08&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">&#39;330&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;xesscorp/xess.pretty:CTS_742C163&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">),</span>
            <span class="n">Part</span><span class="p">(</span><span class="s2">&quot;Device&quot;</span><span class="p">,</span> <span class="s1">&#39;R_Pack08&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="s1">&#39;330&#39;</span><span class="p">,</span> <span class="n">footprint</span><span class="o">=</span><span class="s1">&#39;xesscorp/xess.pretty:CTS_742C163&#39;</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="n">TEMPLATE</span><span class="p">),</span>
        <span class="p">],</span>
    <span class="p">):</span>

    <span class="n">width</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">anodes</span><span class="o">.</span><span class="n">width</span><span class="p">,</span> <span class="n">cathodes</span><span class="o">.</span><span class="n">width</span><span class="p">)</span>

    <span class="n">leds</span> <span class="o">=</span> <span class="n">width</span> <span class="o">*</span> <span class="n">led_type</span>

    <span class="c1"># The bus width indicates the number of LEDs (and, hence, the number of</span>
    <span class="c1"># resistors) that are needed. Pick the best resistor array and subtract its</span>
    <span class="c1"># size from the number of resistors that are needed. If more resistors are</span>
    <span class="c1"># still required, repeat the loop until the number drops to zero.</span>
    <span class="n">r_needed</span> <span class="o">=</span> <span class="n">width</span>  <span class="c1"># The number of resistors that are currently needed.</span>
    <span class="n">rs</span> <span class="o">=</span> <span class="p">[]</span>           <span class="c1"># Store the selected resistors here.</span>
    <span class="n">left_pins</span> <span class="o">=</span> <span class="p">[]</span>    <span class="c1"># List of pins on the left side of the selected resistors.</span>
    <span class="n">right_pins</span> <span class="o">=</span> <span class="p">[]</span>   <span class="c1"># List of pins on the right side of the selected resistors.</span>

    <span class="k">while</span> <span class="n">r_needed</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>  <span class="c1"># Loop as long as resistors are needed.</span>

        <span class="c1"># Pick the best resistor for the current number of resistors that are needed.</span>
        <span class="c1"># If the needed number is larger than the list of resistors, then pick</span>
        <span class="c1"># the largest available resistor array (which will be at the end of the list).</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">r_type</span> <span class="o">=</span> <span class="n">r_types</span><span class="p">[</span><span class="n">r_needed</span><span class="p">]</span>
        <span class="k">except</span> <span class="ne">IndexError</span><span class="p">:</span>
            <span class="n">r_type</span> <span class="o">=</span> <span class="n">r_types</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>  <span class="c1"># Pick the largest resistor array.</span>

        <span class="n">r</span> <span class="o">=</span> <span class="n">r_type</span><span class="p">()</span>  <span class="c1"># Instantiate the selected resistor.</span>
        <span class="n">rs</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">r</span><span class="p">)</span>  <span class="c1"># Add the resistor to the list of selected resistors.</span>

        <span class="n">num_pins</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">pins</span><span class="p">)</span>  <span class="c1"># Number of pins on the selected resistor&#39;s package.</span>
        <span class="n">num_resistors</span> <span class="o">=</span> <span class="n">num_pins</span> <span class="o">//</span> <span class="mi">2</span>  <span class="c1"># Each resistor takes up two pins on the package.</span>

        <span class="c1"># Store the pins on the left and right sides of the resistor.</span>
        <span class="c1"># The pins increase from 1 ... num_pins/2 on the left side, and decrease from</span>
        <span class="c1"># num_pins ... num_pins/2+1 on the right side. This keeps the left and</span>
        <span class="c1"># right pin of each resistor in the package aligned between the lists.</span>
        <span class="n">left_pins</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span> <span class="n">r</span><span class="p">[</span>       <span class="mi">1</span><span class="p">:</span><span class="n">num_pins</span><span class="o">//</span><span class="mi">2</span>  <span class="p">])</span>
        <span class="n">right_pins</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">r</span><span class="p">[</span><span class="n">num_pins</span><span class="p">:</span><span class="n">num_pins</span><span class="o">//</span><span class="mi">2</span><span class="o">+</span><span class="mi">1</span><span class="p">])</span>

        <span class="c1"># Subtract the resistors in the selected package from the number that</span>
        <span class="c1"># are needed and loop until that number goes to zero.</span>
        <span class="n">r_needed</span> <span class="o">-=</span> <span class="n">num_resistors</span>

    <span class="c1"># The number of resistors needed may not fit exactly into the number of </span>
    <span class="c1"># resistors selected (e.g., an eight-resistor array might be used when seven</span>
    <span class="c1"># resistors are needed). Therefore, trim the pin lists to the number of</span>
    <span class="c1"># resistors that are needed. (This may leave some pins on the last-selected</span>
    <span class="c1"># array unconnected.) Also, put them on buses so they&#39;ll be easy to connect to.</span>
    <span class="n">left_pins</span>  <span class="o">=</span> <span class="n">Bus</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="n">left_pins</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="n">width</span><span class="p">])</span>
    <span class="n">right_pins</span> <span class="o">=</span> <span class="n">Bus</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="n">right_pins</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="n">width</span><span class="p">])</span>

    <span class="n">anodes</span> <span class="o">+=</span> <span class="p">[</span><span class="n">led</span><span class="p">[</span><span class="s1">&#39;A&#39;</span><span class="p">]</span> <span class="k">for</span> <span class="n">led</span> <span class="ow">in</span> <span class="n">leds</span><span class="p">]</span>     <span class="c1"># Connect LED anodes to anode inputs.</span>
    <span class="n">left_pins</span> <span class="o">+=</span> <span class="p">[</span><span class="n">led</span><span class="p">[</span><span class="s1">&#39;K&#39;</span><span class="p">]</span> <span class="k">for</span> <span class="n">led</span> <span class="ow">in</span> <span class="n">leds</span><span class="p">]</span>  <span class="c1"># Connect LED cathodes to left side of resistors.</span>
    <span class="n">cathodes</span> <span class="o">+=</span> <span class="n">right_pins</span>                   <span class="c1"># Connect right side of resistors to cathode inputs.</span>
</code></pre></div>

<h3 id="postmortem">Postmortem</h3>
<p>OK, that's it!
I went from a limited module that built four, common-cathode LEDs all the way to
a general-purpose module that handles any number of common-cathode or common-anode LEDs
using a combination of discrete and array resistors.
The price I paid for this generality was more complex, less-understandable code 
and the time it took to write it.
That's because more conditional code is needed to handle different use-cases
and edge conditions.
Often, the extra effort isn't worth it because a circuit is limited to
a narrow set of applications.
But for common-place circuitry (like LEDs, buttons, etc.), the features
supported by SKiDL and Python (querying bus widths, making multiple connections
with a single statement, conditional execution, iterative looping) make the
creation of parameterized, general-purpose modules less tedious.</p>
		</div> <!--/#entry-content-->
	</div> <!--/#main-->
</div>  <!--/#post-->

		</div>

		<div id="footer">
			<p> </p>
		</div><!-- /#footer -->
	</div><!-- /#container -->
	<div style="display:none"></div>
</body>
</html>